import { _decorator, Component, Node, Vec2, tween, v3, UITransform, BlockInputEvents } from "cc";
import { DEV } from "cc/env";

const { ccclass, property } = _decorator;

/**
 * 弹窗基类
 */
@ccclass
export default class PopupBase<Options = any> extends Component {

    @property({ type: Node, tooltip: DEV && '弹窗主题' })
    public main: Node;

    /** 显示/隐藏动画时长 */
    public animDuration: number = 0.3;

    /** 用于拦截点击的节点 */
    protected blocker: Node = null;

    /** 弹窗选项 */
    protected options: Options = null;

    /**
     * 显示弹窗
     * @param options 
     * @param durations 
     * @returns 
     */
    public show(options?: Options, duration: number = this.animDuration): Promise<void> {
        return new Promise<void>(res => {
            this.options = options;
            const main = this.main;
            main.active = true;
            main.setScale(0.3, 0.3, 1.0);
            this.init(this.options);
            this.updateDisplay(this.options);

            tween(main)
                .to(duration, { scale: v3(0.1, 1.0, 1.0) }, { easing: 'backOut' })
                .call(() => {
                    this.onShow && this.onShow();
                    res();
                })
                .start();
        })
    }

    /**
     * 隐藏 弹窗
     * @param suspended 是否挂起
     * @param duration 动画时间
     * @returns 
     */
    public hide(suspended: boolean = false, duration: number = this.animDuration): Promise<void> {
        return new Promise<void>(res => {
            const node = this.node;
            // 动画时长不为0时，拦截点击事件(避免误操作)
            if (duration !== 0) {
                let blocker = this.blocker;
                if (!blocker) {
                    blocker = this.blocker = new Node('blocker');
                    blocker.addComponent(UITransform);
                    blocker.addComponent(BlockInputEvents);
                    blocker.setParent(node);
                    blocker.getComponent(UITransform).setContentSize(node.getComponent(UITransform).contentSize);
                }
                blocker.active = true;
            }

            tween(this.main)
                .to(duration, { scale: v3(0.5, 0.5, 1.0) }, { easing: 'backIn' })
                .call(() => {
                    this.blocker && (this.blocker.active = false);
                    node.active = false;
                    this.onHide && this.onHide(suspended);
                    res();
                    this.finishCallback && this.finishCallback(suspended);
                })

        });
    }


    /**
    * 初始化（派生类请重写此函数以实现自定义逻辑）
    */
    protected init(options: Options) { }

    /**
     * 更新样式（派生类请重写此函数以实现自定义样式）
     * @param options 弹窗选项
     */
    protected updateDisplay(options: Options) { }

    /**
     * 弹窗已完全展示（派生类请重写此函数以实现自定义逻辑）
     */
    protected onShow() { }

    /**
     * 弹窗已完全隐藏（派生类请重写此函数以实现自定义逻辑）
     * @param suspended 是否被挂起
     */
    protected onHide(suspended: boolean) { }

    /**
     * 弹窗流程结束回调（注意：该回调为 PopupManager 专用，重写 hide 函数时记得调用该回调）
     */
    protected finishCallback: (suspended: boolean) => void = null;

    /**
     * 设置弹窗完成回调（该回调为 PopupManager 专用）
     * @param callback 回调
     */
    public setFinishCallback(callback: (suspended: boolean) => void) {
        this.finishCallback = callback;
    }
}